// 题目描述
// 875. 爱吃香蕉的珂珂
// 中等
// 540
// 珂珂喜欢吃香蕉。这里有 n 堆香蕉，第 i 堆中有 piles[i] 根香蕉。警卫已经离开了，将在 h 小时后回来。
// 珂珂可以决定她吃香蕉的速度 k （单位：根/小时）。每个小时，她将会选择一堆香蕉，从中吃掉 k 根。如果这堆香蕉少于 k 根，她将吃掉这堆的所有香蕉，然后这一小时内不会再吃更多的香蕉。
// 珂珂喜欢慢慢吃，但仍然想在警卫回来前吃掉所有的香蕉。
// 返回她可以在 h 小时内吃掉所有香蕉的最小速度 k（k 为整数）。
//   示例 1：
// 输入：piles = [3,6,7,11], h = 8
// 输出：4
// 示例 2：
// 输入：piles = [30,11,23,4,20], h = 5
// 输出：30
// 示例 3：
// 输入：piles = [30,11,23,4,20], h = 6
// 输出：23
//   提示：
// 1 <= piles.length <= 104
// piles.length <= h <= 109
// 1 <= piles[i] <= 109
// 通过次数
// 138K
// 提交次数
// 279.3K
// 通过率
// 49.4%
// https://leetcode.cn/problems/koko-eating-bananas

/**
 * @param {number[]} piles
 * @param {number} h
 * @return {number}
 */
var minEatingSpeed = function (piles, h) {
  // 这类应用二分搜索的应用题一般需要三步走
  // 1. 构造单调函数 fx
  // 2. 初始化 fx 的定义域 [left, right]
  // 3. 套用二分搜索查找 x

  /**
   * 吃香蕉所花的时间（构造单调函数）
   * @param x 吃香蕉的速度：x根/小时
   */
  function getEatingDuration(x) {
    let duration = 0
    for (let i = 0; i < piles.length; i++) {
      const cost = piles[i]
      if (x >= cost) {
        ++duration
      } else {
        duration += Math.ceil(cost / x)
      }
    }

    return duration
  }

  let [left, right] = piles.reduce(([left, right], cur) => {
    return [Math.min(left, cur), right + cur]
  }, [0, 0])
  while (left <= right) {
    const mid = left + Math.floor((right - left) / 2)
    const duration = getEatingDuration(mid)
    if (duration === h) {
      right = mid - 1
    } else if (duration < h) {
      right = mid - 1
    } else if (duration > h) {
      left = mid + 1
    }
  }

  return left
}

console.log(
  minEatingSpeed(
    [30, 11, 23, 4, 20],
    6
  )
)





